let moment = require("moment"); //日期格式化(使用)
let request = require("request");
const uuid = require("uuid/v4");
const UserAgent = require('user-agents');

module.exports = {
  // 队列
  ArrayOutputQueue: function () {
    var arr = [];
    //入队操作  
    this.push = function (element) {
      if (typeof element === "object" && element.length) {
        for (var i = 0; i < element.length; i++) {
          var v = element[i];
          arr.push(v);
        }
      } else {
        arr.push(element);
      }
      return true;
    }
    //出队操作  
    this.pop = function () {
      return arr.shift();
    }
    //指定出队操作  
    this.popByKey = function (key) {
      let item = {};
      arr.map((val, i) => {
        if (val.key === key) {
          item = val;
          arr.splice(i, 1);
        }
      })
      return item;
    }
    //获取队首  
    this.getFront = function () {
      return arr[0];
    }
    //获取队尾  
    this.getRear = function () {
      return arr[arr.length - 1]
    }
    //清空队列  
    this.clear = function () {
      arr = [];
    }
    //获取队长  
    this.size = function () {
      return arr.length;
    }
    this.get = function () {
      return arr;
    }
    this.toString = function () {
      return JSON.stringify(arr);
    }
  },
  // redis队列
  RedisTaskQueue: function ({ name }) {
    try {
      const queueName = `redis_queue:${name}`;
      //入队操作  
      this.push = async function (element) {
        let count = 0;
        if (Object.prototype.toString.call(element) === "[object Array]") {
          for (let i = 0; i < element.length; i++) {
            const v = element[i];
            count += await global.redis.zadd(queueName, v);
          }
        } else if (Object.prototype.toString.call(element) === "[object object]") {
          count += await global.redis.zadd(queueName, element)
        }
        return count;//返回新增条数
      }
      //获取队长  
      this.size = async function () {
        return await global.redis.zcard(queueName);
      }
      //出队(取第一个,并移除)
      this.pop = async function () {
        try {
          const info = await global.redis.zrange(queueName);
          if (info) await global.redis.zrem(queueName, info);
          return info ? JSON.parse(info) : null;
        } catch (error) {
          return null;
        }
      }
      //清空队列  
      this.clear = async function () {
        return await global.redis.del(queueName);
      }
    } catch (error) {
      console.error(`RedisQueue Error redis_queue:${name},${this.date()},msg=>${error.message}`);
    }
  },
  /**
   * @description 线程暂停
   * @param {time} time 毫秒数
   * @author zengbao
   */
  sleep: function (time) {
    var promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, time);
    });
    return promise;
  },
  /**
   * @description 获取当前访问用户IP
   * @param {request} req
   * @author 蜂鸟配送
   */
  getClientIp: function (req) {
    return (
      req.headers["x-forwarded-for"] ||
      req.connection.remoteAddress ||
      req.socket.remoteAddress ||
      req.connection.socket.remoteAddress
    );
  },
  /**
   * @description 取随机数
   * @param {number} Min 最小数
   * @param {number} Max 最大数
   * @author 蜂鸟配送
   */
  randomNumBoth: function (Min, Max) {
    let Range = Max - Min;
    let Rand = Math.random();
    let num = Min + Math.round(Rand * Range); //四舍五入
    return num;
  },
  /**
   * @description 格式化日期
   * @param {date||time} mDate 日期
   * @param {string} format 日期格式
   * @author 蜂鸟配送
   */
  date: function (mDate, format) {
    return moment((mDate ? new Date(mDate) : new Date())).format(
      format || "YYYY-MM-DD HH:mm:ss"
    );
  },
  /**
   * @description 成功回调
   * @param {request} res 响应
   * @param {object} data 传入的返回参数
   * @param {boolean} isa 是否打印
   * @author 蜂鸟配送
   */
  rSuccess: function (res, data, isa) {
    data = data ? data : {};
    let param = {
      success: true,
      message: data.msg || data.message || "操作成功！",
      code: data.code || 1,
      data: data.data
    };
    isa ? console.log(JSON.stringify(param)) : "";
    res.send(param);
  },
  /**
   * @description 失败回调
   * @param {request} res 响应
   * @param {object} data 传入的返回参数
   * @author 蜂鸟配送
   */
  rError: function (res, data, resCode = 500) {
    let param = {
      success: false,
      message: data.msg || data.message || "服务器异常!",
      code: data.code || -1,
      data: data.data
    };
    console.log(JSON.stringify(param));
    resCode ? res.send(resCode || 404, param) : res.send(param);
  },
  returnIp: function () {
    return (
      Math.floor(Math.random() * (10 - 255) + 255) +
      "." +
      Math.floor(Math.random() * (10 - 255) + 255) +
      "." +
      Math.floor(Math.random() * (10 - 255) + 255) +
      "." +
      Math.floor(Math.random() * (10 - 255) + 255)
    )
  },
  /**
   * @description 发送请求
   * @param {object} opt 提交参数
   * @author 一枚前端
   */
  $ajax: function (opt = {}) {
    return new Promise((resolve, reject) => {
      try {
        if (!opt.url) throw new Error("url , is not null");
        const headers = opt.headers || {};
        let user_agent = new UserAgent({ deviceCategory: 'mobile' });
        delete opt.headers;
        const options = {
          method: 'GET',
          timeout: 10000,
          json: true,
          headers: {
            'Accept-Encoding': 'gzip',
            'Connection': 'keep-alive',
            'User-Agent': user_agent.toString(),
            ...headers
          },
          ...opt
        };
        request(options, (error, response, body) => {
          if (body) {
            resolve(body);
          } else {
            reject(error);
          }
        });
      } catch (error) {
        reject(error);
      }
    })
  },
  //显示内存情况
  memoryUsage: function () {
    let mem = process.memoryUsage();
    let format = function (bytes) {
      return (bytes / 1024 / 1024).toFixed(2) + "MB";
    };
    console.error(
      "Process: heapTotal " +
      format(mem.heapTotal) +
      " heapUsed " +
      format(mem.heapUsed) +
      " rss " +
      format(mem.rss)
    );
  },
  // 函数防抖(一直执行的话只执行最后一次调用)
  debounce: function (fn = () => { }, wait = 300) {
    var timeout = null;
    return function () {
      if (timeout !== null) clearTimeout(timeout);
      timeout = setTimeout(fn, wait);
    }
  }
};
